bitkeeper revision 1.1041.16.1 (40ec1cc7JZD3Tq_wg7Ea5ZjrczQ0_A)
authormjw@wray-m-3.hpl.hp.com <mjw@wray-m-3.hpl.hp.com>
Wed, 7 Jul 2004 15:54:47 +0000 (15:54 +0000)
committermjw@wray-m-3.hpl.hp.com <mjw@wray-m-3.hpl.hp.com>
Wed, 7 Jul 2004 15:54:47 +0000 (15:54 +0000)
Starting to call xfrd from xend.

13 files changed:
.rootkeys
tools/Makefile
tools/libxutil/sys_net.c
tools/python/xen/xend/XendDomain.py
tools/python/xen/xend/XendMigrate.py
tools/xfrd/Make.xfrd
tools/xfrd/connection.c
tools/xfrd/connection.h
tools/xfrd/sxpr_parser.c [new file with mode: 0644]
tools/xfrd/sxpr_parser.h [new file with mode: 0644]
tools/xfrd/xen_domain.c
tools/xfrd/xfrd.c
tools/xfrd/xfrdClient.py

index d8edf89b738c62332349e236b29271f038456b95..17a4abdc09a4687f7c60ea62297ae4e86fb86f73 100644 (file)
--- a/.rootkeys
+++ b/.rootkeys
 40e9808e99OcM547cKMTfmCVSoWVAw tools/xfrd/select.h
 40e9808e5_PLdodqVOSx0b4T_f5aeg tools/xfrd/sxpr.c
 40e9808e0O4sHZtkDv5hlSqjYcdQAQ tools/xfrd/sxpr.h
+40ec1cc6SIiGbynOi-1NtPesOlzF-Q tools/xfrd/sxpr_parser.c
+40ec1cc6wpvvGxZiq4EFvNOcw0tUFg tools/xfrd/sxpr_parser.h
 40e9808eF3NVldqRNS5IHM8gbFAvpw tools/xfrd/xdr.c
 40e9808ezXzoRHm7pybXU69NtnjimA tools/xfrd/xdr.h
 40e9808edpUtf4bJ8IbqClPJj_OvbA tools/xfrd/xen_domain.c
index b366034eb28b0cf754a85db1a5e2d0ca09dbd64b..58934639bbdc0e07c4cdf38628463b1e3b451aee 100644 (file)
@@ -6,6 +6,7 @@ all:
        $(MAKE) -C examples
        $(MAKE) -C xentrace
        $(MAKE) -C python
+       $(MAKE) -C xfrd
 
 install: all
        $(MAKE) -C libxutil install
@@ -14,6 +15,7 @@ install: all
        $(MAKE) -C examples install
        $(MAKE) -C xentrace install
        $(MAKE) -C python install
+       $(MAKE) -C xfrd install
 
 dist: $(TARGET)
        $(MAKE) prefix=`pwd`/../../install dist=yes install
@@ -26,4 +28,5 @@ clean:
        $(MAKE) -C examples clean
        $(MAKE) -C xentrace clean
        $(MAKE) -C python clean
+       $(MAKE) -C xfrd clean
 
index 0e7ac5d6389c955eb3f35527d98217974103734b..f38d919d9c68592dc3dfe1d23cd843b79745513f 100644 (file)
 #include "sys_net.h"
 #include "sys_string.h"
 
+#ifdef __KERNEL__
+#  include <linux/errno.h>
+#else
+#  include <errno.h>
+#endif
+
 /** @file
  * All network data are kept in network order and only converted to
  * host order for display. Network data includes IP addresses, port numbers and
@@ -80,7 +86,7 @@ inline static int indexof(const char *s, int n, char c){
  *
  * @param s input string
  * @param address where to put the address
- * @return 0 on success, -1 on error
+ * @return 0 on success, negative on error
  */
 int get_inet_addr(const char *s, unsigned long *address){
     // Number of bits in a byte.
@@ -96,7 +102,7 @@ int get_inet_addr(const char *s, unsigned long *address){
     unsigned long addr = 0;
     unsigned long v;
     int i;
-    int err = -1;
+    int err = -EINVAL;
     // Bit shift for the current byte.
     int shift = BYTE_BITS * (WORD_BYTES - 1);
     char buf[64];
@@ -168,18 +174,18 @@ int inet_aton(const char *address, struct in_addr *inp){
  *
  * @param name input hostname or address string
  * @param address where to put the address
- * @return 1 if address found OK, 0 otherwise
+ * @return 0 if address found OK, nonzero otherwise
  */
 int get_host_address(const char *name, unsigned long *address){
 #ifdef __KERNEL__
-    return get_inet_addr(name, address) == 0;
+    return get_inet_addr(name, address);
 #else
     struct hostent *host = gethostbyname(name);
     if(!host){
-        return 0;
+        return -EINVAL;
     }
     *address = ((struct in_addr *)(host->h_addr))->s_addr;
-    return 1;
+    return 0;
 #endif
 }
 
@@ -187,33 +193,33 @@ int get_host_address(const char *name, unsigned long *address){
  *
  * @param name service name
  * @param port where to put the port
- * @return 1 if service port found OK, 0 otherwise
+ * @return 0 if service port found OK, negative otherwise
  */
 int get_service_port(const char *name, unsigned long *port){
 #ifdef __KERNEL__
-    return 0;
+    return -ENOSYS;
 #else
     struct servent *service;
     service = getservbyname(name, 0);
     if(!service){
-        return 0;
+        return -EINVAL;
     }
     *port = service->s_port;
-    return 1;
+    return 0;
 #endif
 }
 
 /** Convert a port number (in network order) to a service name.
  *
  * @param port the port number
- * @return service name if found OK, 0 otherwise
+ * @return service name if found OK, NULL otherwise
  */
 char *get_port_service(unsigned long port){
 #ifdef __KERNEL__
-    return 0;
+    return NULL;
 #else
     struct servent *service = getservbyport(port, 0);
-    return (service ? service->s_name : 0);
+    return (service ? service->s_name : NULL);
 #endif
 }
 
@@ -221,19 +227,27 @@ char *get_port_service(unsigned long port){
  *
  * @param s input to convert
  * @param port where to put the port
- * @return 1 if port found OK, 0 otherwise
+ * @return 0 if port found OK, -1 otherwise
  */
 int convert_service_to_port(const char *s, unsigned long *port){
-    int ok = 0;
+    int err = 0;
     unsigned long value;
-    if(convert_atoul(s, &value)){
-        ok = get_service_port(s, &value);
+    printf("%s> %s\n", __FUNCTION__, s);
+    if(convert_atoul(s, &value) == 0){
+        int ok = (0 <= value) && (value <= PORT_MAX);
+        printf("> value = %ld\n", value);
+        if(ok){
+            value = htons((unsigned short)value);
+        } else {
+            err = -EINVAL;
+        }
     } else {
-        ok = (0 <= value) && (value <= PORT_MAX);
-        value = htons((unsigned short)value);
+        printf("> get_service_port...\n");
+        err = get_service_port(s, &value);
     }
-    *port = (ok ? value : 0);
-    return ok;
+    *port = (err ? 0: value);
+    printf("%s< err=%d\n", __FUNCTION__, err);
+    return err;
 }
 
 #define MAC_ELEMENT_N  6 // Number of elements in a MAC address.
index 8b9db8101ccf246129ca72a7096ea717e82a408a..d52c93dda6733bd9556feccec2c11deecfff9603 100644 (file)
@@ -19,6 +19,7 @@ xroot = XendRoot.instance()
 import XendDB
 import XendDomainInfo
 import XendConsole
+import XendMigrate
 import EventServer
 
 from xen.xend.server import SrvDaemon
@@ -423,7 +424,9 @@ class XendDomain:
         """
         # Need a cancel too?
         # Don't forget to cancel restart for it.
-        pass
+        dom = int(id)
+        xmigrate = XendMigrate.instance()
+        return xmigrate.migrate_begin(dom, dst)
 
     def domain_save(self, id, dst, progress=0):
         """Save domain state to file, destroy domain on success.
index a598913792144923de26174614916b32d35317c3..a4a4183cebe8e6123ecf9d989632f8d5defa5bb7 100644 (file)
@@ -14,11 +14,6 @@ import sxp
 import XendDB
 import EventServer; eserver = EventServer.instance()
 
-from xen.xend.packing import SxpPacker, SxpUnpacker
-from xen.xend import XendDomain
-xd = XendDomain.instance()
-
-
 XFRD_PORT = 8002
 
 XFR_PROTO_MAJOR = 1
@@ -27,55 +22,63 @@ XFR_PROTO_MINOR = 0
 class Migrate(Protocol):
 
     def __init__(self, minfo):
-        self.packer = None
-        self.unpacker = None
+        self.parser = sxp.Parser()
         self.minfo = minfo
 
     def connectionMade(self):
-        self.packer = SxpPacker(self.transport)
-        self.unpacker = SxpPacker()
         # Send hello.
-        self.packer.pack(['xfr.hello', XFR_PROTO_MAJOR, XFR_PROTO_MINOR])
+        self.request(['xfr.hello', XFR_PROTO_MAJOR, XFR_PROTO_MINOR])
         # Send migrate.
         vmconfig = self.minfo.vmconfig()
         if not vmconfig:
             self.loseConnection()
             return
-        self.packer.pack(['xfr.migrate',
-                          self.minfo.src_dom,
-                          vmconfig,
-                          self.minfo.dst_host,
-                          self.minfo.dst_port])
+        self.request(['xfr.migrate',
+                      self.minfo.src_dom,
+                      vmconfig,
+                      self.minfo.dst_host,
+                      self.minfo.dst_port])
+
+    def request(self, req):
+        sxp.show(req, out=self.transport)
+        self.transport.write(' \n')
+
+    def loseConnection(self):
+        self.transport.loseConnection()
 
     def connectionLost(self, reason):
         self.minfo.closed(reason)
 
-    def dataReceived(self, data):
-        try:
-            self.unpacker.reset(data)
-            val = self.unpacker.unpack()
-            print 'dataReceived>', 'val=', val
-            op = val[0]
-            op.replace('.', '_')
-            if op.startwith('xfr_'):
-                fn = getattr(self, op, self.unknown)
-            else:
-                fn = self.unknown
-            fn(val)
-        except Exception, ex:
-            print 'dataReceived>', ex
-            pass
+    def dispatch(self, val):
+        op = sxp.name(val)
+        op = op.replace('.', '_')
+        if op.startswith('xfr_'):
+            fn = getattr(self, op, self.unknown)
+        else:
+            fn = self.unknown()
+        fn(val)
 
+    def dataReceived(self, data):
+        self.parser.input(data)
+        if self.parser.ready():
+            val = self.parser.get_val()
+            self.dispatch(val)
+        if self.parser.at_eof():
+            self.loseConnection()
+            
     def unknown(self, val):
         print 'unknown>', val
 
     def xfr_progress(self, val):
         print 'xfr_progress>', val
 
-    def xfr_error(self, val):
+    def xfr_err(self, val):
         # If we get an error with non-zero code the migrate failed.
         # An error with code zero indicates hello success.
-        err = int(val[1])
+        print 'xfr_err>', val
+        v = sxp.child(val)
+        print 'xfr_err>', type(v), v
+        err = int(sxp.child(val))
         if not err: return
         self.minfo.error(err);
         self.loseConnection()
@@ -83,14 +86,15 @@ class Migrate(Protocol):
     def xfr_ok(self, val):
         # An ok indicates migrate completed successfully, and contains
         # the new domain id on the remote system.
-        dom = int(val[1])
+        print 'xfr_ok>', val
+        dom = int(sxp.child(val))
         self.minfo.ok(dom)
         self.loseConnection()
 
 class MigrateClientFactory(ClientFactory):
 
     def __init__(self, minfo):
-        ClientFactory.__init__(self)
+        #ClientFactory.__init__(self)
         self.minfo = minfo
 
     def startedConnecting(self, connector):
@@ -116,7 +120,7 @@ class XendMigrateInfo:
         self.state = 'begin'
         self.src_host = socket.gethostname()
         self.src_dom = dom
-        self.dst_host = dst
+        self.dst_host = host
         self.dst_port = port
         self.dst_dom = None
         self.start = 0
@@ -139,12 +143,18 @@ class XendMigrateInfo:
         return sxpr
 
     def vmconfig(self):
-        dominfo = xd.domain_get(self.dom)
+        print 'vmconfig>'
+        from xen.xend import XendDomain
+        xd = XendDomain.instance()
+
+        dominfo = xd.domain_get(self.src_dom)
+        print 'vmconfig>', type(dominfo), dominfo
         if dominfo:
-            val = return sxp.to_string(dominfo)
+            val = sxp.to_string(dominfo.sxpr())
         else:
             val = None
-        return None
+        print 'vmconfig<', 'val=', type(val), val
+        return val
 
     def error(self, err):
         self.state = 'error'
@@ -153,7 +163,7 @@ class XendMigrateInfo:
         self.state = 'ok'
         self.dst_dom = dom
 
-    def close(self):
+    def closed(self, reason=None):
         if self.state =='ok':
             eserver.inject('xend.migrate.ok', self.sxpr())
         else:
@@ -208,15 +218,15 @@ class XendMigrate:
     def migrate_get(self, id):
         return self.migrate.get(id)
     
-    def migrate_begin(self, dom, host):
+    def migrate_begin(self, dom, host, port=XFRD_PORT):
         # Check dom for existence, not migrating already.
         # Subscribe to migrate notifications (for updating).
         id = self.nextid()
-        info = XenMigrateInfo(id, dom, host, XFRD_PORT)
+        info = XendMigrateInfo(id, dom, host, port)
         self._add_migrate(id, info)
         mcf = MigrateClientFactory(info)
         reactor.connectTCP('localhost', XFRD_PORT, mcf)
-        return info.deferred
+        return info
 
 def instance():
     global inst
index 39f3afd3c5f0b50f4907410c32ba4f92a9b1ca2f..bb746d6befa095146f7fd418926d2fffddde1d53 100644 (file)
@@ -15,7 +15,7 @@ UTIL_LIB_SRC += lzi_stream.c
 UTIL_LIB_SRC += marshal.c
 UTIL_LIB_SRC += string_stream.c
 UTIL_LIB_SRC += sxpr.c
-#UTIL_LIB_SRC += sxpr_parser.c
+UTIL_LIB_SRC += sxpr_parser.c
 UTIL_LIB_SRC += sys_net.c
 UTIL_LIB_SRC += sys_string.c
 #UTIL_LIB_SRC += util.c
index 26dca9968b7b964285555e6a63f9617ef186a840..36f2ca8475150111c5ac21cfc55e05eb66dfb81a 100644 (file)
@@ -8,6 +8,7 @@
 #include "connection.h"
 #include "file_stream.h"
 #include "lzi_stream.h"
+#include "sxpr_parser.h"
 
 #define dprintf(fmt, args...) fprintf(stdout, "[DEBUG] %s" fmt, __FUNCTION__, ##args)
 #define wprintf(fmt, args...) fprintf(stderr, "[WARN]  %s" fmt, __FUNCTION__, ##args)
@@ -161,3 +162,34 @@ void Conn_close(Conn *conn){
     if(conn->out) IOStream_close(conn->out);
     shutdown(conn->sock, 2);
 }
+
+int Conn_sxpr(Conn *conn, Sxpr *sxpr){
+    int err = 0;
+    Sxpr val = ONONE;
+    int c = 0;
+
+    dprintf(">\n");
+    if(!conn->parser){
+        conn->parser = Parser_new();
+        set_error_stream(conn->parser, iostdout);
+    }
+    while(!err && c >= 0 && !Parser_ready(conn->parser)){
+        c = IOStream_getc(conn->in);
+        printf("%c", (char)c);
+        if(c < 0){
+            err = Parser_input_eof(conn->parser);
+        } else {
+            err = Parser_input_char(conn->parser, c);
+        }
+    }
+    if(Parser_ready(conn->parser)){
+        val = Parser_get_val(conn->parser);
+    }
+    if(err){
+        objfree(val);
+        val = ONONE;
+    }
+    *sxpr = val;
+    dprintf("< err=%d\n", err);
+    return err;
+}
index 790c01f1e8938fe222c91c56b8304fa2a71c91a7..2b67e767bafbb9d73fb6db6a35c8f80ba6471d34 100644 (file)
@@ -5,6 +5,7 @@
 #include <netinet/in.h>
 
 #include "iostream.h"
+#include "sxpr_parser.h"
 
 /** A connection.
  * The underlying transport is a socket. 
@@ -15,6 +16,7 @@ typedef struct Conn {
     int sock;
     IOStream *in;
     IOStream *out;
+    Parser *parser;
 } Conn;
 
 enum {
@@ -29,4 +31,6 @@ extern int Conn_init(Conn *conn, int flags, int sock, struct sockaddr_in addr);
 extern int Conn_connect(Conn *conn, int flags, struct in_addr ipaddr, uint16_t port);
 extern void Conn_close(Conn *conn);
 
+extern int Conn_sxpr(Conn *conn, Sxpr *sxpr);
+
 #endif /* ! _VFC_CONNECTION_H_ */
diff --git a/tools/xfrd/sxpr_parser.c b/tools/xfrd/sxpr_parser.c
new file mode 100644 (file)
index 0000000..dbe386a
--- /dev/null
@@ -0,0 +1,943 @@
+
+#ifdef __KERNEL__
+#  include <linux/config.h>
+#  include <linux/module.h>
+#  include <linux/kernel.h>
+#  include <linux/string.h>
+#  include <linux/errno.h>
+#else
+#  include <stdlib.h>
+#  include <errno.h>
+#endif
+
+#include "iostream.h"
+#include "lexis.h"
+#include "sxpr_parser.h"
+#include "sys_string.h"
+#include "enum.h"
+
+/** @file
+ * Sxpr parsing.
+ *
+ * So that the parser does not leak memory, all sxprs constructed by
+ * the parser must be freed on error.  On successful parse the sxpr
+ * returned becomes the responsibility of the caller.
+ *
+ * @author Mike Wray <mike.wray@hpl.hp.com>
+ */
+
+#define dprintf(fmt, args...) IOStream_print(iostdout, "[DEBUG] %s" fmt, __FUNCTION__, ##args)
+#define printf(fmt, args...)   IOStream_print(iostdout, fmt, ##args)
+
+static void reset(Parser *z);
+static int inputchar(Parser *p, char c);
+static int savechar(Parser *p, char c);
+extern void parse_error(Parser *in);
+extern void parse_error_id(Parser *in, ParseErrorId id);
+
+static int begin_start(Parser *p, char c);
+static int state_start(Parser *p, char c);
+static int end_start(Parser *p);
+
+static int begin_comment(Parser *p, char c);
+static int state_comment(Parser *p, char c);
+static int end_comment(Parser *p);
+
+static int begin_string(Parser *p, char c);
+static int state_string(Parser *p, char c);
+static int end_string(Parser *p);
+static int state_escape(Parser *p, char c);
+static int state_octal(Parser *p, char c);
+static int state_hex(Parser *p, char c);
+
+static int begin_atom(Parser *p, char c);
+static int state_atom(Parser *p, char c);
+static int end_atom(Parser *p);
+
+static int state_list(Parser *p, char c);
+static int begin_list(Parser *p, char c);
+static int end_list(Parser *p);
+
+/** Print a parse error.
+ *
+ * @param in parser
+ * @param msg format followed by printf arguments
+ */
+void eprintf(Parser *in, char *msg, ...){
+    va_list args;
+    if(in->error_out){
+        va_start(args, msg);
+        IOStream_vprint(in->error_out, msg, args);
+        va_end(args);
+    }
+}
+
+/** Print a parse warning.
+ *
+ * @param in parser
+ * @param msg format followed by printf arguments
+ */
+void wprintf(Parser *in, char *msg, ...){
+    va_list args;
+    if(in->error_out){
+        va_start(args, msg);
+        IOStream_vprint(in->error_out, msg, args);
+        va_end(args);
+    }
+}
+
+/*============================================================================*/
+
+/** Record defining the message for a parse error. */
+typedef struct {
+  ParseErrorId id;
+  char *message;
+} ParseError;
+
+/** Format for printing parse error messages. */
+#define PARSE_ERR_FMT "parse error> line %3d, column %2d: %s"
+
+/** Message catalog for the parse error codes. */
+static ParseError catalog[] = {
+  { PARSE_ERR_UNSPECIFIED,            "unspecified error" },
+  { PARSE_ERR_NOMEM,                  "out of memory" },
+  { PARSE_ERR_UNEXPECTED_EOF,         "unexpected end of input" },
+  { PARSE_ERR_TOKEN_TOO_LONG,         "token too long" },
+  { PARSE_ERR_INVALID_SYNTAX,         "syntax error" },
+  { PARSE_ERR_INVALID_ESCAPE,         "invalid escape" },
+  { 0, NULL }
+};
+
+/** Number of entries in the message catalog. */
+const static int catalog_n = sizeof(catalog)/sizeof(ParseError);
+
+void ParserState_free(ParserState *z){
+    if(!z) return;
+    objfree(z->val);
+    deallocate(z);
+}
+
+int ParserState_new(ParserStateFn *fn, char *name,
+                    ParserState *parent, ParserState **val){
+    int err = 0;
+    ParserState *z;
+    z = ALLOCATE(ParserState);
+    if(z){
+        z->name = name;
+        z->fn = fn;
+        z->parent = parent;
+        z->val = ONULL;
+    } else {
+        err = -ENOMEM;
+    }
+    if(!err) *val = z;
+    return err;
+}
+
+/** Free a parser.
+ * No-op if the parser is null.
+ *
+ * @param z parser 
+ */
+void Parser_free(Parser *z){
+    if(!z) return;
+    objfree(z->val);
+    z->val = ONONE;
+    deallocate(z);
+}
+
+/** Create a new parser. The error stream defaults to null.
+ */
+Parser * Parser_new(void){
+    Parser *z = ALLOCATE(Parser);
+    int err = -ENOMEM;
+  
+    if(!z) goto exit;
+    err = 0;
+    reset(z);
+  exit:
+    if(err){
+        Parser_free(z);
+        z = NULL;
+    }
+    return z;
+}
+
+/** Get the next character.
+ * Records the character read in the parser,
+ * and sets the line and character counts.
+ *
+ * @param p parser
+ * @return error flag: 0 on success, non-zero on error
+ */
+static int inputchar(Parser *p, char c){
+    int err = 0;
+    if(c=='\n'){
+        p->line_no++;
+        p->char_no = 0;
+    } else {
+        p->char_no++;
+    }
+    return err;
+}
+
+static int savechar(Parser *p, char c){
+    int err = 0;
+    if(p->buf_i >= p->buf_n){
+        err = -ENOMEM;
+        goto exit;
+    }
+    p->buf[p->buf_i] = c;
+    p->buf_i++;
+  exit:
+    return err;
+}
+
+int Parser_input_char(Parser *p, char c){
+    int err = 0;
+    if(at_eof(p)){
+        //skip;
+    } else {
+        inputchar(p, c);
+    }
+    if(!p->state){
+        err = begin_start(p, c);
+        if(err) goto exit;
+    }
+    err = p->state->fn(p, c);
+  exit:
+    return err;
+}
+
+int Parser_input_eof(Parser *p){
+    int err = 0;
+    p->eof = 1;
+    err = Parser_input_char(p, IOSTREAM_EOF);
+    return err;
+}
+
+int Parser_input(Parser *p, char *buf, int buf_n){
+    int err = 0;
+    int i = 0;
+    if(buf_n <= 0){
+        err = Parser_input_eof(p);
+        goto exit;
+    }
+    for(i = 0; i<buf_n; i++){
+        err = Parser_input_char(p, buf[i]);
+        if(err) goto exit;
+    }
+  exit:
+    err = (err < 0 ? err : buf_n);
+    return err;
+}
+
+int Parser_push(Parser *p, ParserStateFn *fn, char *name){
+    int err = 0;
+    err = ParserState_new(fn, name, p->state, &p->state);
+    return err;
+}
+        
+int Parser_pop(Parser *p){
+    int err = 0;
+    ParserState *s = p->state;
+    p->state = s->parent;
+    ParserState_free(s);
+    return err;
+}
+
+int Parser_return(Parser *p){
+    int err = 0;
+    Sxpr val = ONONE;
+    if(!p->state){
+        err = -EINVAL;
+        goto exit;
+    }
+    val = p->state->val;
+    p->state->val = ONONE;
+    err = Parser_pop(p);
+    if(err) goto exit;
+    if(p->state){
+        err = cons_push(&p->state->val, val);
+    } else {
+        val = nrev(val);
+        p->val = val;
+    }
+  exit:
+    if(err){
+        objfree(val);
+    }
+    return err;
+}
+
+/** Determine if a character is a separator.
+ *
+ * @param p parser
+ * @param c character to test
+ * @return 1 if a separator, 0 otherwise
+ */
+static int is_separator(Parser *p, char c){
+    return in_sep_class(c);
+}
+
+/** Return the current token.
+ * The return value points at the internal buffer, so
+ * it must not be modified (or freed). Use copy_token() if you need a copy.
+ *
+ * @param p parser
+ * @return token
+ */
+char *peek_token(Parser *p){
+    return p->buf;
+}
+
+/** Return a copy of the current token.
+ * The returned value should be freed when finished with.
+ *
+ * @param p parser
+ * @return copy of token
+ */
+char *copy_token(Parser *p){
+    return strdup(peek_token(p));
+}
+
+static int do_intern(Parser *p){
+    int err = 0;
+    Sxpr obj = intern(peek_token(p));
+    if(NOMEMP(obj)){
+        err = -ENOMEM;
+    } else {
+        p->state->val = obj;
+    }
+    return err;
+}
+
+static int do_string(Parser *p){
+    int err = 0;
+    Sxpr obj;
+    obj = string_new(peek_token(p));
+    if(NOMEMP(obj)){
+        err = -ENOMEM;
+    } else {
+        p->state->val = obj;
+    }
+    return err;
+}
+
+void newtoken(Parser *p){
+    memset(p->buf, 0, p->buf_n);
+    p->buf_i = 0;
+    p->tok_begin_line = p->line_no;
+    p->tok_begin_char = p->char_no;
+}
+
+int get_escape(char c, char *d){
+    int err = 0;
+    switch(c){
+    case 'a':            *d = '\a'; break;
+    case 'b':            *d = '\b'; break;
+    case 'f':            *d = '\f'; break;
+    case 'n':            *d = '\n'; break;
+    case 'r':            *d = '\r'; break;
+    case 't':            *d = '\t'; break;
+    case 'v':            *d = '\v'; break;
+    case c_escape:       *d = c_escape; break;
+    case c_single_quote: *d = c_single_quote; break;
+    case c_double_quote: *d = c_double_quote; break;
+    default:
+        err = -EINVAL;
+    }
+    return err;
+}
+
+int Parser_ready(Parser *p){
+    return CONSP(p->val) || (p->start_state && CONSP(p->start_state->val));
+}
+
+Sxpr Parser_get_val(Parser *p){
+    Sxpr v = ONONE;
+    if(CONSP(p->val)){
+        v = CAR(p->val);
+        p->val = CDR(p->val);
+    } else if (CONSP(p->start_state->val)){
+        p->val = p->start_state->val;
+        p->val = nrev(p->val);
+        p->start_state->val = ONULL;
+        v = CAR(p->val);
+        p->val = CDR(p->val);
+    }        
+    return v;
+}
+
+Sxpr Parser_get_all(Parser *p){
+    Sxpr v = ONULL;
+    if(CONSP(p->val)){
+        v = p->val;
+        p->val = ONONE;
+    } else if(CONSP(p->start_state->val)){
+        v = p->start_state->val;
+        p->start_state->val = ONULL;
+        v = nrev(v);
+    }
+    return v;
+}
+    
+int begin_start(Parser *p, char c){
+    int err = 0;
+    err = Parser_push(p, state_start, "start");
+    if(err) goto exit;
+    p->start_state = p->state;
+  exit:
+    return err;
+}
+
+int state_start(Parser *p, char c){
+    int err = 0;
+    if(at_eof(p)){
+        err = end_start(p);
+    } else if(in_space_class(c)){
+        //skip
+    } else if(in_comment_class(c)){
+        begin_comment(p, c);
+    } else if(c == c_list_open){
+        begin_list(p, c);
+    } else if(c == c_list_close){
+        parse_error(p);
+        err = -EINVAL;
+    } else if(in_string_quote_class(c)){
+        begin_string(p, c);
+    } else if(in_printable_class(c)){
+        begin_atom(p, c);
+    } else if(c == 0x04){
+        //ctrl-D, EOT: end-of-text.
+        Parser_input_eof(p);
+    } else {
+        parse_error(p);
+        err = -EINVAL;
+    }
+    return err;
+}
+
+int end_start(Parser *p){
+    int err = 0;
+    err = Parser_return(p);
+    return err;
+}
+
+int begin_comment(Parser *p, char c){
+    int err = 0;
+    err = Parser_push(p, state_comment, "comment");
+    if(err) goto exit;
+    err = inputchar(p, c);
+  exit:
+    return err;
+}
+
+int state_comment(Parser *p, char c){
+    int err = 0;
+    if(c == '\n' || at_eof(p)){
+        err = end_comment(p);
+    } else {
+        err = inputchar(p, c);
+    }
+    return err;
+}
+
+int end_comment(Parser *p){
+    return Parser_pop(p);
+}
+
+int begin_string(Parser *p, char c){
+    int err = 0;
+    err = Parser_push(p, state_string, "string");
+    if(err) goto exit;
+    newtoken(p);
+    p->state->delim = c;
+  exit:
+    return err;
+}
+
+int state_string(Parser *p, char c){
+    int err = 0;
+    if(at_eof(p)){
+        parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
+        err = -EINVAL;
+    } else if(c == p->state->delim){
+        err = end_string(p);
+    } else if(c == '\\'){
+        err = Parser_push(p, state_escape, "escape");
+    } else {
+        err = savechar(p, c);
+    }
+    return err;
+}
+
+int end_string(Parser *p){
+    int err = 0;
+    err = do_string(p);
+    if(err) goto exit;
+    err = Parser_return(p);
+  exit:
+    return err;
+}
+
+int state_escape(Parser *p, char c){
+    int err = 0;
+    char d;
+    if(at_eof(p)){
+        parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
+        err = -EINVAL;
+        goto exit;
+    }
+    if(get_escape(c, &d) == 0){
+        err = savechar(p, d);
+        if(err) goto exit;
+        err = Parser_pop(p);
+    } else if(c == 'x'){
+        p->state->fn = state_hex;
+        p->state->ival = 0;
+        p->state->count = 0;
+    } else {
+        p->state->fn = state_octal;
+        p->state->ival = 0;
+        p->state->count = 0;
+        err = Parser_input_char(p, c);
+    }
+  exit:
+    return err;
+}
+
+int octaldone(Parser *p){
+    int err = 0;
+    char d = (char)(p->state->ival & 0xff);
+    err = Parser_pop(p);
+    if(err) goto exit;
+    err = Parser_input_char(p, d);
+  exit:
+    return err;
+}
+
+int octaldigit(Parser *p, char c){
+    int err = 0;
+    p->state->ival *= 8;
+    p->state->ival += c - '0'; 
+    p->state->count++;
+    if(err) goto exit;
+    if(p->state->ival < 0 || p->state->ival > 0xff){
+        parse_error(p);
+        err = -EINVAL;
+        goto exit;
+    }
+    if(p->state->count == 3){
+        err = octaldone(p);
+    }
+  exit:
+    return err;
+}
+
+int state_octal(Parser *p, char c){
+    int err = 0;
+    if(at_eof(p)){
+        parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
+        err = -EINVAL;
+        goto exit;
+    } else if('0' <= c && c <= '7'){
+        err = octaldigit(p, c);
+    } else {
+        err = octaldone(p);
+        if(err) goto exit;
+        Parser_input_char(p, c);
+    }
+  exit:
+    return err;
+}
+
+int hexdone(Parser *p){
+    int err = 0;
+    char d = (char)(p->state->ival & 0xff);
+    err = Parser_pop(p);
+    if(err) goto exit;
+    err = Parser_input_char(p, d);
+  exit:
+    return err;
+}
+    
+int hexdigit(Parser *p, char c, char d){
+    int err = 0;
+    p->state->ival *= 16;
+    p->state->ival += c - d; 
+    p->state->count++;
+    if(err) goto exit;
+    if(p->state->ival < 0 || p->state->ival > 0xff){
+        parse_error(p);
+        err = -EINVAL;
+        goto exit;
+    }
+    if(p->state->count == 2){
+        err = hexdone(p);
+    }
+  exit:
+    return err;
+}
+    
+int state_hex(Parser *p, char c){
+    int err = 0;
+    if(at_eof(p)){
+        parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
+        err = -EINVAL;
+        goto exit;
+    } else if('0' <= c && c <= '9'){
+        err = hexdigit(p, c, '0');
+    } else if('A' <= c && c <= 'F'){
+        err = hexdigit(p, c, 'A');
+    } else if('a' <= c && c <= 'f'){
+        err = hexdigit(p, c, 'a');
+    } else if(p->state->count){
+        err =hexdone(p);
+        if(err) goto exit;
+        Parser_input_char(p, c);
+    }
+  exit:
+    return err;
+}
+
+int begin_atom(Parser *p, char c){
+    int err = 0;
+    err = Parser_push(p, state_atom, "atom");
+    if(err) goto exit;
+    newtoken(p);
+    err = savechar(p, c);
+  exit:
+    return err;
+}
+
+int state_atom(Parser *p, char c){
+    int err = 0;
+    if(at_eof(p)){
+        err = end_atom(p);
+    } else if(is_separator(p, c) ||
+              in_space_class(c) ||
+              in_comment_class(c)){
+        err = end_atom(p);
+        if(err) goto exit;
+        err = Parser_input_char(p, c);
+    } else {
+        err = savechar(p, c);
+    }
+  exit:
+    return err;
+}
+
+int end_atom(Parser *p){
+    int err = 0;
+    err = do_intern(p);
+    if(err) goto exit;
+    err = Parser_return(p);
+  exit:
+    return err;
+}
+
+int state_list(Parser *p, char c){
+    int err = 0;
+    if(at_eof(p)){
+        parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
+        err = -EINVAL;
+    } else if(c == c_list_close){
+        p->state->val = nrev(p->state->val);
+        err = end_list(p);
+    } else {
+        err = state_start(p, c);
+    }
+    return err;
+    
+}
+
+int begin_list(Parser *p, char c){
+    return Parser_push(p, state_list, "list");
+}
+
+int end_list(Parser *p){
+    return Parser_return(p);
+}
+
+/** Reset the fields of a parser to initial values.
+ *
+ * @param z parser
+ */
+static void reset(Parser *z){
+  IOStream *error_out = z->error_out;
+  int flags = z->flags;
+  memzero(z, sizeof(Parser));
+  z->buf_n = sizeof(z->buf) - 1;
+  z->buf_i = 0;
+  z->line_no = 1;
+  z->char_no = 0;
+  z->error_out = error_out;
+  z->flags = flags;
+}
+
+/** Set the parser error stream.
+ * Parse errors are reported on the the error stream if it is non-null.
+ * 
+ * @param z parser
+ * @param error_out error stream
+ */
+void set_error_stream(Parser *z, IOStream *error_out){
+  if(z){
+    z->error_out = error_out;
+  }
+}
+
+/** Get the parser error message for an error code.
+ *
+ * @param id error code
+ * @return error message (empty string if the code is unknown)
+ */
+static char *get_message(ParseErrorId id){
+  int i;
+  for(i=0; i<catalog_n; i++){
+    if(id == catalog[i].id){
+      return catalog[i].message;
+    }
+  }
+  return "";
+}
+
+/** Get the line number.
+ *
+ * @param in parser
+ */
+int get_line(Parser *in){
+  return in->line_no;
+}
+
+/** Get the column number.
+ *
+ * @param in parser
+ */
+int get_column(Parser *in){
+  return in->char_no;
+}
+
+/** Get the line number the current token started on.
+ *
+ * @param in parser
+ */
+int get_tok_line(Parser *in){
+  return in->tok_begin_line;
+}
+
+/** Get the column number the current token started on.
+ *
+ * @param in parser
+ */
+int get_tok_column(Parser *in){
+  return in->tok_begin_char;
+}
+
+/** Report a parse error.
+ * Does nothing if the error stream is null or there is no error.
+ *
+ * @param in parser
+ */
+static void report_error(Parser *in){
+  if(in->error_out && in->err){
+    char *msg = get_message(in->err);
+    char *tok = peek_token(in);
+    IOStream_print(in->error_out, PARSE_ERR_FMT,
+                  get_tok_line(in), get_tok_column(in), msg);
+    if(tok && tok[0]){
+        IOStream_print(in->error_out, " '%s'", tok);
+    }
+    IOStream_print(in->error_out, "\n");
+  }
+}
+
+/** Get the error message for the current parse error code.
+ * Does nothing if there is no error.
+ *
+ * @param in parser
+ * @param buf where to place the message
+ * @param n maximum number of characters to place in buf
+ * @return current error code (zero for no error)
+ */
+int parse_error_message(Parser *in, char *buf, int n){
+    if(in->err){
+        char *msg = get_message(in->err);
+        snprintf(buf, n, PARSE_ERR_FMT, get_tok_line(in), get_tok_column(in), msg);
+    }
+    return in->err;
+}
+
+/** Flag an unspecified parse error. All subsequent reads will fail.
+ *
+ * @param in parser
+ */
+void parse_error(Parser *in){
+    parse_error_id(in, PARSE_ERR_INVALID_SYNTAX);
+}
+
+/** Flag a parse error. All subsequent reads will fail.
+ * Does not change the parser error code if it is already set.
+ *
+ * @param in parser
+ * @param id error code
+ */
+void parse_error_id(Parser *in, ParseErrorId id){
+    if(!in->err){
+        in->err = id;
+        report_error(in);
+    }
+}
+
+/** Test if the parser's error flag is set.
+ *
+ * @param in parser
+ * @return 1 if set, 0 otherwise
+ */
+int has_error(Parser *in){
+    return (in->err > 0);
+}
+
+/** Test if the parser is at end of input.
+ *
+ * @param in parser
+ * @return 1 if at EOF, 0 otherwise
+ */
+int at_eof(Parser *p){
+    return p->eof;
+}
+
+//#define SXPR_PARSER_MAIN
+#ifdef SXPR_PARSER_MAIN
+/* Stuff for standalone testing. */
+
+#include "file_stream.h"
+#include "string_stream.h"
+
+int stringof(Sxpr exp, char **s){
+    int err = 0;
+    if(ATOMP(exp)){
+        *s = atom_name(exp);
+    } else if(STRINGP(exp)){
+        *s = string_string(exp);
+    } else {
+        err = -EINVAL;
+        *s = NULL;
+    }
+    return err;
+}
+
+int child_string(Sxpr exp, Sxpr key, char **s){
+    int err = 0;
+    Sxpr val = sxpr_child_value(exp, key, ONONE);
+    err = stringof(val, s);
+    return err;
+}
+
+int intof(Sxpr exp, int *v){
+    int err = 0;
+    char *s;
+    unsigned long l;
+    if(INTP(exp)){
+        *v = OBJ_INT(exp);
+    } else {
+        err = stringof(exp, &s);
+        if(err) goto exit;
+        err = convert_atoul(s, &l);
+        *v = (int)l;
+    }
+ exit:
+    return err;
+}
+
+int child_int(Sxpr exp, Sxpr key, int *v){
+    int err = 0;
+    Sxpr val = sxpr_child_value(exp, key, ONONE);
+    err = intof(val, v);
+    return err;
+}
+
+int eval_vnet(Sxpr exp){
+    int err = 0;
+    Sxpr oid = intern("id");
+    int id;
+    err = child_int(exp, oid, &id);
+    if(err) goto exit;
+    dprintf("> vnet id=%d\n", id);
+ exit:
+    dprintf("< err=%d\n", err);
+    return err;
+}
+
+int eval_connect(Sxpr exp){
+    int err = 0;
+    Sxpr ovif = intern("vif");
+    Sxpr ovnet = intern("vnet");
+    char *vif;
+    int vnet;
+
+    err = child_string(exp, ovif, &vif);
+    if(err) goto exit;
+    err = child_int(exp, ovnet, &vnet);
+    if(err) goto exit;
+    dprintf("> connect vif=%s vnet=%d\n", vif, vnet);
+ exit:
+    dprintf("< err=%d\n", err);
+    return err;
+}
+
+int eval(Sxpr exp){
+    int err = 0;
+    Sxpr oconnect = intern("connect");
+    Sxpr ovnet = intern("vnet");
+    
+    if(sxpr_elementp(exp, ovnet)){
+        err = eval_vnet(exp);
+    } else if(sxpr_elementp(exp, oconnect)){
+        err = eval_connect(exp);
+    } else {
+        err = -EINVAL;
+    }
+    return err;
+}
+
+/** Main program for testing.
+ * Parses input and prints it.
+ *
+ * @param argc number of arguments
+ * @param argv arguments
+ * @return error code
+ */
+int main(int argc, char *argv[]){
+    Parser *pin;
+    int err = 0;
+    char buf[1024];
+    int k;
+    Sxpr obj;
+    //Sxpr l, x;
+    int i = 0;
+
+    pin = Parser_new();
+    set_error_stream(pin, iostdout);
+    dprintf("> parse...\n");
+    while(1){
+        k = fread(buf, 1, 1, stdin);
+        err = Parser_input(pin, buf, k);
+        while(Parser_ready(pin)){
+            obj = Parser_get_val(pin);
+            printf("obj %d\n", i++);
+            objprint(iostdout, obj, 0); printf("\n");
+        }
+        if(k <= 0) break;
+    }
+/*     obj = Parser_get_all(pin); */
+/*     for(l = obj ; CONSP(l); l = CDR(l)){ */
+/*         x = CAR(l); */
+/*         objprint(iostdout, x, 0); printf("\n"); */
+/*         eval(x); */
+/*     } */
+    dprintf("> err=%d\n", err);
+    return 0;
+}
+#endif
diff --git a/tools/xfrd/sxpr_parser.h b/tools/xfrd/sxpr_parser.h
new file mode 100644 (file)
index 0000000..64a4176
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of the
+ * License, or  (at your option) any later version. This library is 
+ * distributed in the  hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#ifndef _XUTIL_SXPR_PARSER_H_
+#define _XUTIL_SXPR_PARSER_H_
+
+#include "sxpr.h"
+#include "iostream.h"
+
+/** @file
+ * Sxpr parsing definitions.
+ */
+
+/** Size of a parser input buffer.
+ * Tokens read must fit into this size (including trailing null).
+ */
+#define PARSER_BUF_SIZE 1024
+
+struct Parser;
+typedef int ParserStateFn(struct Parser *, char c);
+
+typedef struct ParserState {
+    struct ParserState *parent;
+    Sxpr val;
+    int ival;
+    int count;
+    char delim;
+    ParserStateFn *fn;
+    char *name;
+} ParserState;
+
+/** Structure representing an input source for the parser.
+ * Can read from any IOStream implementation.
+ */
+typedef struct Parser {
+    Sxpr val;
+    /** Error reporting stream (null for no reports). */
+    IOStream *error_out;
+    int eof;
+    /** Error flag. Non-zero if there has been a read error. */
+    int err;
+    /** Line number on input (from 1). */
+    int line_no;
+    /** Column number of input (reset on new line). */
+    int char_no;
+    /** Lookahead character. */
+    char c;
+    /** Buffer for reading tokens. */
+    char buf[PARSER_BUF_SIZE];
+    /** Size of token buffer. */
+    int buf_n;
+    int buf_i;
+    /** Line the last token started on. */
+    int tok_begin_line;
+    /** Character number the last token started on. */
+    int tok_begin_char;
+    /** Parsing flags. */
+    int flags;
+    ParserState *state;
+    ParserState *start_state;
+} Parser;
+
+/** Parser error codes. */
+typedef enum {
+    PARSE_ERR_NONE=0,
+    PARSE_ERR_UNSPECIFIED,
+    PARSE_ERR_NOMEM,
+    PARSE_ERR_UNEXPECTED_EOF,
+    PARSE_ERR_TOKEN_TOO_LONG,
+    PARSE_ERR_INVALID_SYNTAX,
+    PARSE_ERR_INVALID_ESCAPE,
+} ParseErrorId;
+
+
+/** Parser flags. */
+//enum {
+//};
+
+/** Raise some parser flags.
+ *
+ * @param in parser
+ * @param flags flags mask
+ */
+inline static void parser_flags_raise(Parser *in, int flags){
+    in->flags |= flags;
+}
+
+/** Lower some parser flags.
+ *
+ * @param in parser
+ * @param flags flags mask
+ */
+inline static void parser_flags_lower(Parser *in, int flags){
+    in->flags &= ~flags;
+}
+
+/** Clear all parser flags.
+ *
+ * @param in parser
+ */
+inline static void parser_flags_clear(Parser *in){
+    in->flags = 0;
+}
+
+extern void Parser_free(Parser *z);
+extern Parser * Parser_new(void);
+extern int Parser_input(Parser *p, char *buf, int buf_n);
+extern int Parser_input_eof(Parser *p);
+extern int Parser_input_char(Parser *p, char c);
+extern void set_error_stream(Parser *z, IOStream *error_out);
+
+extern int parse_error_message(Parser *in, char *buf, int n);
+extern int has_error(Parser *in);
+extern int at_eof(Parser *in);
+
+int Parser_ready(Parser *p);
+Sxpr Parser_get_val(Parser *p);
+Sxpr Parser_get_all(Parser *p);
+
+#endif /* ! _XUTIL_SXPR_PARSER_H_ */
index 5c5f7c5befa02e22feaa1b658564f37e643bac25..4c197e8396ee37b19d1933c05d6b13dbbc6ef7e9 100644 (file)
@@ -38,7 +38,7 @@ int xen_domain_snd(Conn *xend, IOStream *io, uint32_t dom, char *vmconfig, int v
         if(d > buf_n) d = buf_n;
         err = marshal_bytes(io, buf, d);
         if(err) goto exit;
-        //dprintf("> k=%d n=%d\n", k, n);
+        dprintf("> k=%d n=%d\n", k, n);
     }
     
   exit:
@@ -68,7 +68,7 @@ int xen_domain_rcv(IOStream *io, uint32_t *dom, char **vmconfig, int *vmconfig_n
         if(d > buf_n) d = buf_n;
         err = unmarshal_bytes(io, buf, d);
         if(err) goto exit;
-        //dprintf("> k=%d n=%d\n", k, n);
+        dprintf("> k=%d n=%d\n", k, n);
     }
   exit:
 #else    
index 18362310754a140d88cd9b32b9ba066bcdc30dba..5dac7be0ba06fbd2d15163987ecf285570a4f816 100644 (file)
@@ -36,7 +36,7 @@
 #include "sys_net.h"
 #include "sys_string.h"
 
-#include "xdr.h"
+//#include "xdr.h"
 #include "enum.h"
 #include "xfrd.h"
 
@@ -362,10 +362,10 @@ int addrof(Sxpr exp, uint32_t *v){
     err = stringof(exp, &h);
     if(err) goto exit;
     if(get_host_address(h, &a)){
-        *v = a;
-    } else {
         err = -EINVAL;
+        goto exit;
     }
+    *v = a;
   exit:
     dprintf("< err=%d v=%x\n", err, *v);
     return err;
@@ -383,11 +383,12 @@ int portof(Sxpr exp, uint16_t *v){
         unsigned long p;
         err = stringof(exp, &s);
         if(err) goto exit;
-        if(get_service_port(s, &p)){
-            *v = p;
-        } else {
+        err = convert_service_to_port(s, &p);
+        if(err){
             err = -EINVAL;
+            goto exit;
         }
+        *v = p;
     }
   exit:
     dprintf("< err=%d v=%u\n", err, *v);
@@ -414,20 +415,12 @@ time_t stats(time_t t0, uint64_t offset, uint64_t memory, float *percent, float
  */
 int xfr_error(Conn *conn, int errcode){
     int err = 0;
+
     if(!conn->out) return -ENOTCONN;
-    err = pack_type(conn->out, T_CONS);
-    if(err) goto exit;
-    err = pack_bool(conn->out, 1);
-    if(err) goto exit;
-    err = pack_sxpr(conn->out, oxfr_err);
-    if(err) goto exit;
-    err = pack_bool(conn->out, 1);
-    if(err) goto exit;
-    err = pack_sxpr(conn->out, mkint(errcode));
-    if(err) goto exit;
-    err = pack_bool(conn->out, 0);
-  exit:
-    return err;
+    if(errcode <0) errcode = -errcode;
+    err = IOStream_print(conn->out, "(%s %d)",
+                         atom_name(oxfr_err), errcode);
+    return (err < 0 ? err : 0);
 }
 
 /** Read a response message - error or ok.
@@ -441,7 +434,7 @@ int xfr_response(Conn *conn){
 
     dprintf(">\n");
     if(!conn->out) return -ENOTCONN;
-    err = unpack_sxpr(conn->in, &sxpr);
+    err = Conn_sxpr(conn, &sxpr);
     if(err) goto exit;
     if(sxpr_elementp(sxpr, oxfr_err)){
         int errcode;
@@ -468,7 +461,7 @@ int xfr_hello(Conn *conn){
     Sxpr sxpr;
     if(!conn->in) return -ENOTCONN;
     dprintf(">\n");
-    err = unpack_sxpr(conn->in, &sxpr);
+    err = Conn_sxpr(conn, &sxpr);
     if(err) goto exit;
     if(!sxpr_elementp(sxpr, oxfr_hello)){
         dprintf("> sxpr_elementp test failed\n");
@@ -503,21 +496,12 @@ int xfr_hello(Conn *conn){
 int xfr_send_hello(Conn *conn){
     int err = 0;
     dprintf(">\n");
-    err = pack_type(conn->out, T_CONS);
-    if(err) goto exit;
-    err = pack_bool(conn->out, 1);
-    if(err) goto exit;
-    err = pack_sxpr(conn->out, oxfr_hello);
-    if(err) goto exit;
-    err = pack_bool(conn->out, 1);
-    if(err) goto exit;
-    err = pack_sxpr(conn->out, mkint(XFR_PROTO_MAJOR));
-    if(err) goto exit;
-    err = pack_bool(conn->out, 1);
-    if(err) goto exit;
-    err = pack_sxpr(conn->out, mkint(XFR_PROTO_MINOR));
-    if(err) goto exit;
-    err = pack_bool(conn->out, 0);
+
+    err = IOStream_print(conn->out, "(%s %d %d)",
+                         atom_name(oxfr_hello),
+                         XFR_PROTO_MAJOR,
+                         XFR_PROTO_MINOR);
+    if(err < 0) goto exit;
     IOStream_flush(conn->out);
     dprintf("> xfr_response...\n");
     err = xfr_response(conn);
@@ -528,55 +512,26 @@ int xfr_send_hello(Conn *conn){
 
 int xfr_send_xfr(Conn *conn, uint32_t vmid){
     int err;
-    err = pack_type(conn->out, T_CONS);
-    if(err) goto exit;
-    err = pack_bool(conn->out, 1);
-    if(err) goto exit;
-    err = pack_sxpr(conn->out, oxfr_xfr);
-    if(err) goto exit;
-    err = pack_bool(conn->out, 1);
-    if(err) goto exit;
-    err = pack_sxpr(conn->out, mkint(vmid));
-    if(err) goto exit;
-    err = pack_bool(conn->out, 0);
-    if(err) goto exit;
-  exit:
-    return err;
+
+    err = IOStream_print(conn->out, "(%s %d)",
+                         atom_name(oxfr_xfr), vmid);
+    return (err < 0 ? err : 0);
 }
 
 int xfr_send_ok(Conn *conn, uint32_t vmid){
     int err = 0;
-    err = pack_type(conn->out, T_CONS);
-    if(err) goto exit;
-    err = pack_bool(conn->out, 1);
-    if(err) goto exit;
-    err = pack_sxpr(conn->out, oxfr_ok);
-    if(err) goto exit;
-    err = pack_bool(conn->out, 1);
-    if(err) goto exit;
-    err = pack_sxpr(conn->out, mkint(vmid));
-    if(err) goto exit;
-    err = pack_bool(conn->out, 0);
-  exit:
-    return err;
+
+    err = IOStream_print(conn->out, "(%s %d)",
+                         atom_name(oxfr_ok), vmid);
+    return (err < 0 ? err : 0);
 }
 
 int xfr_send_suspend(Conn *conn, uint32_t vmid){
     int err = 0;
 
-    err = pack_type(conn->out, T_CONS);
-    if(err) goto exit;
-    err = pack_bool(conn->out, 1);
-    if(err) goto exit;
-    err = pack_sxpr(conn->out, oxfr_suspend);
-    if(err) goto exit;
-    err = pack_bool(conn->out, 1);
-    if(err) goto exit;
-    err = pack_sxpr(conn->out, mkint(vmid));
-    if(err) goto exit;
-    err = pack_bool(conn->out, 0);
-  exit:
-    return err;
+    err = IOStream_print(conn->out, "(%s %d)",
+                         atom_name(oxfr_suspend), vmid);
+    return (err < 0 ? err : 0);
 }
 
 /** Get vm state. Send transfer message.
@@ -594,11 +549,12 @@ int xfr_send_state(XfrState *state, Conn *xend, Conn *peer){
     // Send xfr message and the domain state.
     err = xfr_send_xfr(peer, state->vmid);
     if(err) goto exit;
-    err = xen_domain_snd(xend, peer->out, state->vmid, state->vmconfig, state->vmconfig_n);
+    err = xen_domain_snd(xend, peer->out,
+                         state->vmid, state->vmconfig, state->vmconfig_n);
     if(err) goto exit;
     IOStream_flush(peer->out);
     // Read the response from the peer.
-    err = unpack_sxpr(peer->in, &sxpr);
+    err = Conn_sxpr(peer, &sxpr);
     if(err) goto exit;
     if(sxpr_elementp(sxpr, oxfr_err)){
         // Error.
@@ -785,10 +741,14 @@ int xfrd_service(Args *args, int peersock, struct sockaddr_in peer_in){
     dprintf(">\n");
     err = Conn_init(conn, flags, peersock, peer_in);
     if(err) goto exit;
+    dprintf(">xfr_hello... \n");
     err = xfr_hello(conn);
     if(err) goto exit;
-    err = unpack_sxpr(conn->in, &sxpr);
+    dprintf("> sxpr...\n");
+    err = Conn_sxpr(conn, &sxpr);
     if(err) goto exit;
+    dprintf("> sxpr=\n");
+    objprint(iostdout, sxpr, PRINT_TYPE); IOStream_print(iostdout, "\n");
     if(sxpr_elementp(sxpr, oxfr_migrate)){
         // Migrate message from xend.
         uint32_t addr;
index b8a355472911a4e8540b32071a71600ab5045f8a..1f1fc22407cc70db3e1e7ad6f1db60c8aa3b6f91 100755 (executable)
@@ -34,13 +34,11 @@ class TCPClient:
         
         self.sockin = self.sock.makefile("r")
         self.sockout = self.sock.makefile("w")
-        self.packer = SxpPacker(self.sockout)
-        self.unpacker = SxpUnpacker(self.sockin)
         #pass
 
     def request(self, req):
         print "request>", req
-        self.packer.pack(req)
+        sxp.show(req, out=self.sockout)
         self.sockout.flush()
         print "request<"
 
@@ -52,10 +50,10 @@ class TCPClient:
 
     def read(self):
         while(1):
-            v = self.unpacker.unpack()
+            v = self.sockin.read()
             print 'read>', v
-            if v[0] == 'xfr.err' and v[1]: return
-            if v[0] == 'xfr.ok': return
+            #if v[0] == 'xfr.err' and v[1]: return
+            #if v[0] == 'xfr.ok': return
 
 XFR_PROTO_MAJOR = 1
 XFR_PROTO_MINOR = 0